/*-*
 * FILENAME  :
 *    $HeadURL$
 *
 * STATUS  :
 *    $Revision$
 *
 *    $Author$
 *    $Date$
 *  
 *    
 * Copyright (c) 2011 Gonalge Ltda. All rights reserved.
 *
 ****************************************************************/

package org.gonalge.rompecabeza.negocio;

import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.io.Serializable;
import java.util.Vector;

import org.gonalge.rompecabeza.dto.Jugador;
import org.gonalge.rompecabeza.dto.Pieza;

/**
 * 
 * @author Geremias Gonzalez
 */
public class Juego implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 5343255090690248010L;

    private int ancho, alto, n;

    private int imagen = 1;

    private ListaPieza piezaTablero = null; // Tablero completo

    private ListaPieza piezaPerdiente = null; // Piezas Pendiente

    private int x = 255, y = 83;

    private Vector<Jugador> jugadores = null;

    private int fil, col;

    public Juego() {
        piezaPerdiente = new ListaPieza();
        jugadores = new Vector<Jugador>();
        piezaTablero = new ListaPieza();

        fil = col = 3;
        piezaTablero.setXY(0, 0);

    }

    public void nuevoJuego(int fil, int col) {
        this.fil = fil;
        this.col = col;
        nuevoJuego();

    }

    public void nuevoJuego() {
        piezaPerdiente.configurar(fil, col);
        piezaPerdiente.desordenar();
        piezaTablero.configurar(fil, col);

        ancho = piezaTablero.getAncho();
        alto = piezaTablero.getAlto();
        n = piezaTablero.getN();
        jugadores.clear();
    }

    // *******************************************************
    private Jugador buscarJugador(String nombre) {
        Jugador jugador = null;
        for (Jugador jug : jugadores) {
            if (jug.getNombre().equals(nombre)) {
                jugador = jug;
                break;
            }
        }
        return jugador;
    }

    public void jugar(String nombre) {
        Jugador jugador = buscarJugador(nombre);

        if (jugador != null) {
            Pieza pieza = jugador.getPieza();

            if (pieza != null) {
                for (int i = 0; i < piezaTablero.length(); i++) {
                    Pieza piezaSel = piezaTablero.getPiesa(i);

                    if (!piezaSel.estado) { // si no a esta ocupado o jugada ese pieza
                        Area a = getArea(piezaSel.getTipo(), piezaSel.getX() + x, piezaSel.getY() + y);

                        if (a.contains(pieza.getX() + ancho / 2, pieza.getY() + alto / 2)) {
                            if (pieza.getEle() == piezaSel.getEle()) {
                                piezaTablero.getPiesa(pieza.getEle() - 1).estado = true;
                                jugador.incrementarAsciertos();
                                jugador.setPieza(null);
                                return;
                            } else {
                                jugador.incrementarFallas();
                                pieza.setXY(jugador.getXS(), jugador.getYS());
                            }
                            break;
                        }
                    }
                }
                piezaPerdiente.setPieza(pieza);
                jugador.setPieza(null);
            }
        }
    }

    public void moverPieza(String Nombre, int x, int y) {
        Jugador jugador = buscarJugador(Nombre);
        if (jugador != null) {
            Pieza pieza = jugador.getPieza();
            if (pieza != null) {
                pieza.setXY(x - ancho / 2, y - alto / 2);
            }
        }
    }

    public void selecionarPieza(String Nombre, int x, int y) {

        for (int i = piezaPerdiente.length() - 1; i >= 0; i--) {
            Pieza p = piezaPerdiente.getPiesa(i);
            Area a = getArea(p.getTipo(), p.getX(), p.getY());

            if (a.contains(x, y)) {
                Jugador jug = buscarJugador(Nombre);
                if (jug != null) {
                    p = piezaPerdiente.eliminarPieza(i);
                    jug.setPieza(p);
                    jug.setXSYS(p.getX(), p.getY());
                }
                return;
            }
        }
    }

    // ******************************************************

    public ListaPieza getPiezaPerdiente() {
        return piezaPerdiente;
    }

    public Jugador getJugadore(int index) {
        return jugadores.get(index);
    }

    public Vector<Jugador> getJugadores() {
        return jugadores;
    }

    public void addJugador(Jugador jugagor) {
        this.jugadores.add(jugagor);
    }

    public int getFil() {
        return fil;
    }

    public int getCol() {
        return col;
    }

    public void setImagen(int imagen) {
        this.imagen = imagen;
    }

    public int getImagen() {
        return imagen;
    }

    public ListaPieza getPiezaTablero() {
        return piezaTablero;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getY() {
        return y;
    }

    // ******************************************************
    private Area cargarfig1(int x, int y) {

        Area a = new Area();

        a.add(new Area(new Rectangle(x + n, y + n, ancho - n, alto - n)));

        a.add(new Area(new RoundRectangle2D.Double(x, y + 3 * n / 2, n * 2 - n / 2, n * 2, n, n)));
        a.subtract(new Area(new RoundRectangle2D.Double(x + ancho - n, y + 3 * n / 2, n * 2, n * 2, n, n)));

        a.add(new Area(new RoundRectangle2D.Double(x + 4 * n / 3, y, n * 2, n * 2 - n / 2, n, n)));
        a.subtract(new Area(new RoundRectangle2D.Double(x + ancho / 2, y + alto - n, n, n * 2, n, n)));

        a.add(new Area(new RoundRectangle2D.Double(x + n, y + alto - n, n, 4 * n / 3, n, n))); // *

        a.subtract(new Area(new RoundRectangle2D.Double(x, y + alto - n, 4 * n / 3, n, n, n)));
        a.add(new Area(new RoundRectangle2D.Double(x + ancho - n, y + alto - n, 4 * n / 3, n, n, n)));

        a.subtract(new Area(new RoundRectangle2D.Double(x + ancho - 4 * n / 3, y, n, n * 2 - n / 2, n, n)));

        return a;
    }

    private Area cargarfig2(int x, int y) {

        Area a = new Area();

        a.add(new Area(new Rectangle(x + n, y + n, ancho - n, alto - n)));

        a.add(new Area(new RoundRectangle2D.Double(x + ancho / 2, y, n, n * 2, n, n)));
        a.subtract(new Area(new RoundRectangle2D.Double(x + 4 * n / 3, y + alto - n, n * 2, n * 2, n, n)));

        a.add(new Area(new RoundRectangle2D.Double(x, y + n, n * 2 - n / 2, n * 2, n, n)));
        a.subtract(new Area(new RoundRectangle2D.Double(x + ancho - n, y + n, n * 2, n * 2, n, n)));

        a.add(new Area(new RoundRectangle2D.Double(x, y + alto - n * 2, n * 2, n, n, n)));
        a.subtract(new Area(new RoundRectangle2D.Double(x + ancho - n, y + alto - n * 2, n * 2, n, n, n)));

        a.subtract(new Area(new RoundRectangle2D.Double(x + n, y, n, 4 * n / 3, n, n))); // *

        a.add(new Area(new RoundRectangle2D.Double(x + ancho - 4 * n / 3, y + alto - n, n, n * 2 - n / 2, n, n)));

        return a;
    }

    public Area getArea(int T, int x, int y) {
        if (T == 1)
            return cargarfig1(x, y);
        else
            return cargarfig2(x, y);
    }

    public int getAsciertos(String nombre) {
        return buscarJugador(nombre).getNroAsciertos();
    }

    public int getFallas(String nombre) {
        return buscarJugador(nombre).getNroFallas();
    }

    public int getMaxAciertos() {
        int max = 0;
        for (Jugador jug : jugadores) {
            if (max < jug.getNroAsciertos())
                max = jug.getNroAsciertos();
        }
        return max;
    }

    public boolean finJuego() {
        return piezaPerdiente.length() == 0;
    }

    public Jugador jugadorGanador(int max) {
        Jugador jugador = null;
        for (Jugador jug : jugadores) {
            if (jug.getNroAsciertos() == max) {
                jugador = jug;
            }
        }
        return jugador;
    }

    public void setPiezaPerdiente(ListaPieza pDesor) {
        this.piezaPerdiente = pDesor;
    }

    public void setJugadores(Vector<Jugador> jugadores) {
        this.jugadores = jugadores;
    }

    public Vector<Byte> getEstadoTablero() {
        Vector<Byte> pos = new Vector<Byte>();
        for (int i = 0; i < piezaTablero.length(); i++) {
            if (piezaTablero.getPiesa(i).estado)
                pos.add((byte) i);

        }
        return pos;
    }

    public void setEstadoTablero(Vector<Byte> pos) {
        for (int i = 0; i < pos.size(); i++)
            piezaTablero.getPiesa(pos.get(i)).estado = true;

    }
}
